import type { IAppLifeCycles } from "./type";

/**
 * 将html隔离为 html、css、js
 */
export const importHtml = async (url: string) => {
  const html = await fetch(url).then((res) => res.text());
  const template = document.createElement("div");
  // template.innerHTML = '<p>hello sub app</p>'
  template.innerHTML = html;

  const scripts = template.querySelectorAll("script");

  // 获取所有js代码
  const getExternalScripts = () => {
    return Promise.all(
      Array.from(scripts).map((script) => {
        const src = script.getAttribute("src");
        /**
         * script分为：
         * 1. 内联代码 <script>...</script>
         * 2. 外部代码 <script src="..."></script>
         */
        if (src) {
          const scriptUrl = src.startsWith("http") ? src : url + src;
          return fetch(scriptUrl).then((res) => res.text());
        } else {
          return Promise.resolve(script.innerHTML);
        }
      })
    );
  };

  // 获取并执行js代码
  const execScripts = async (): Promise<IAppLifeCycles> => {
    const scripts = await getExternalScripts();
    // 手动构造一个commonjs环境，便于从umd产物中获取内容(module.exports = factory(); factory就是导出的内容)
    const module = { exports: {} };
    // @ts-ignore
    const exports = module.exports; // 没有使用也需要写（具体可以参考umd打包产物）
    scripts.forEach((code) => {
      eval(code);
    });
    // 子应用通过umd进行打包构建，但是通过获取到子应用window中的名字太麻烦
    // return (window as any)['webpack-vue']
    // 可以参考 my-qiankun/umd.js
    // 我们可以构造一个commonjs环境，让他以commonjs方式获取，不从window拿（写在上面）
    type SubAppExports = IAppLifeCycles & {
      [key: string]: any;
    };
    return module.exports as SubAppExports;
  };

  return {
    template,
    getExternalScripts,
    execScripts,
  };
};
